package edu.stanford.prpl.app.prpltalk.android;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import edu.stanford.prpl.app.prpltalk.PRPLTalk.BuddyInfo;

import android.location.Location;
import android.provider.Contacts.People;
import android.telephony.PhoneNumberUtils;
import android.util.Log;

/**
* Manages the list of contacts. 
* This class is a singleton and manages a list of all contacts 
* and their location. It is responsible for adding and removing 
* contacts and also for location update in a thread safe way.
*/
public class ContactManager 
{
	/** 
	 * Static instance of the contact manager. 
	 */
	private static ContactManager manager = new ContactManager();
		
	/** 
	 * Map containing all the available contacts (except for the my contact), 
	 * in particular all contacts stored on the phone (offline) 
	 * and online contacts.
	 * Mapping is from PrPl email identifiers to Contact objects.
	 */
	private final Map<String, Contact> contactsMap;

	/**
	 * Instance of the my contact.
	 */
	private Contact myContact;
	
	/** 
	 * Map containing all the available locations 
	 * (online contacts only except the my contact). 
	 */
	private long minutesUpdateInterval;
	
    private static final String TAG = "MyActivity";

	
	/**
	 * Instantiates a new contact manager.
	 */
	private ContactManager() 
	{ 
		contactsMap = new HashMap<String, Contact>();
		minutesUpdateInterval = 10; // Default 10 minutes

		setMyContact("You", "you@prpl.stanford.edu");
	}	
	
		
	/**
	 * Adds a new {@link Contact} with the given BuddyInfo object 
	 * 
	 * Not Implemented for PrPlTalk:
	 * or updates the Location of an existing one.
	 *
	 * @param contactInfo PrPl BuddyInfo object containing info about contact
	 * @param loc current location of the new contact or new location if this is an update
	 */
	public void addOrUpdateOnlineContact(BuddyInfo contactInfo, Location loc)
	{
		// Is the contact already there?
		synchronized(this)
		{	
			// contactInfo.identity.getKey() gets the email string
			String emailContact = contactInfo.identity.getKey();
			Contact cont = contactsMap.get(emailContact);

			// the contact is available
			if (cont != null)
			{
				// Do nothing for now
			}
			else
			{
				cont = new Contact(contactInfo, false);
				cont.setOnline();	
				contactsMap.put(emailContact, cont);
				Log.d(TAG, "Added "+emailContact+"(Name="+cont.getName()+",Email="+cont.getEmail()+") to contact list!");
			}
		}
	}
	
	
	
	/**
	 * Delete a {@link Contact} with the given Email ID
	 * @param contactId Email ID of contact to be deleted
	 */
	public void deleteContact(String contactId)
	{
		if (contactId == null)
		   return;	
		contactsMap.remove(contactId);
	}	
	
	/**
	 * Delete the list of given {@link Contact}s with the given Email IDs 
	 * @param contactIds List of contacts to be deleted by their email IDs
	 */
	public void deleteContacts(List<String> contactIds)
	{
		if (contactIds == null)
		   return;
		
		for (String emailId : contactIds) 
		{
			contactsMap.remove(emailId);
		}
	}	

	
	/**
	 * Retrieves a Contact given its email
	 * 
	 * @param emailContact the email of the contact 
	 *                    that should be retrieved
	 * @return the contact having the given email
	 */
	public Contact getContact(String emailContact)
	{
		if (myContact.getEmail().equals(emailContact))
			return myContact;
		else
		    return contactsMap.get(emailContact);
	}
	

	/**
	 * Retrieve instance of the main contact
	 * 
	 * @return the my contact
	 */
	public Contact getMyContact()
	{
		return myContact;
	}

	/**
	 * Gets the single instance of ContactManager.
	 * 
	 * @return single instance of ContactManager
	 */
	public static ContactManager getInstance() 
	{
		return manager;
	}


	/**
	 * Cleans up both the contact map and the location map
	 */
	public void clearContactManager() 
	{
		contactsMap.clear();
	}

	
	/**
	 * Retrieves a map containing mappings 
	 * between email identifiers and contact objects.
	 * 
	 * @return copy of the inner contact map 
	 */
	public Map<String, Contact> getAllContacts()
	{
		Map<String, Contact> cMap 
		= new HashMap<String, Contact>();

		synchronized (this) 
		{
			for (String email : contactsMap.keySet()) 
			{
				cMap.put(new String(email), new Contact(contactsMap.get(email)));
			}
		}

		return cMap;
	}


	/**
	 * Sets my contact info, given its name & email.
	 * @param name my contact's name
	 * @param emailContact my contact's email
	 */
	public void setMyContact(String name, String emailContact) 
	{
		myContact = new Contact(name, emailContact, true);
		myContact.setOnline();		
	}
	
	
	/**
	 * Retrieves a map containing mappings 
	 * between email identifiers and contact objects.
	 * 
	 * @return copy of the inner contact map 
	 */
	public void updateAllContacts(BuddyInfo[] contactsArray)
	{
		for (int i = 0; i < contactsArray.length; i++)
		{
		    addOrUpdateOnlineContact(contactsArray[i], null);	
		}
	}
	
	
	public long getUpdateInterval()
	{
		return minutesUpdateInterval;
	}
	
	public void setUpdateInterval(int mins)
	{
		minutesUpdateInterval = mins;
	}	
}


